{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "29e5c911-fa2d-4593-8565-3b7bb127b53d",
   "metadata": {},
   "source": [
    "# LangChain 核心模块 Agent - Self ask with search\n",
    "\n",
    "- Google 搜索对接\n",
    "    - 第三方平台：https://serpapi.com\n",
    "    - LangChain API 封装：`SerpAPIWrapper`\n",
    "- LangChain Agent 模块使用\n",
    "    - Agent 类型：`SELF_ASK_WITH_SEARCH`\n",
    "    - Agent 实例化：`initialize_agent` 方法\n",
    " \n",
    "https://python.langchain.com/docs/modules/agents/agent_types/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2866704f-c203-4c97-8221-c2ecadc52b4c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "# 更换为自己的 Serp API KEY\n",
    "os.environ[\"SERPAPI_API_KEY\"] = \"1e3c93e0753ac224098370cd71da86150c6609caba6b5aaa307e04b72a5006e1\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "add0b59e-9e30-41a1-9a4e-bacf8aefb3e9",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain import OpenAI, SerpAPIWrapper\n",
    "from langchain.agents import initialize_agent, AgentType, Tool\n",
    "\n",
    "llm = OpenAI(temperature=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "7047f1b0-a29c-497e-badc-d02fbcbf4082",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 实例化查询工具\n",
    "search = SerpAPIWrapper()\n",
    "tools = [\n",
    "    Tool(\n",
    "        name=\"Intermediate Answer\",\n",
    "        func=search.run,\n",
    "        description=\"useful for when you need to ask with search\",\n",
    "    )\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "08a5daa3-fc7a-4ce9-aa46-ad4a6d31be74",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 实例化 SELF_ASK_WITH_SEARCH Agent\n",
    "self_ask_with_search = initialize_agent(\n",
    "    tools, llm, agent=AgentType.SELF_ASK_WITH_SEARCH, verbose=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "508c39d7-05d9-4486-83bc-924cd6a1c499",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m Yes.\n",
      "Follow up: 什么时候举办的成都大运会？\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3mFri, Jul 28, 2023, 8:00 AM – Tue, Aug 8, 2023\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mFollow up: 成都大运会是第几届大运会？\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3m2021年夏季世界大学生运动会（英语：2021 Summer World University Games）简称为2021年成都大运会或成都大运会，是第31届夏季世界大学生运动会，原定于2021年于中国四川省成都市举行，后因2019冠状病毒病疫情等原因二次延期，最终改至2023年7月28日至8月8日举行。\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mSo the final answer is: 第31届\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'第31届'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 实际运行 Agent，查询问题（正确）\n",
    "self_ask_with_search.run(\n",
    "    \"成都举办的大运会是第几届大运会？\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "5fe1f2de-f982-4953-9e8e-7f99a8289975",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m Yes.\n",
      "Follow up: 什么是2023年大运会？\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3m['The 2023 FISU Summer World University Games, officially known as the 2023 Summer Universiade or the XXXII Summer World University Games, and commonly known as Yekaterinburg 2023 or Ekaterinburg 2023, ...', '2023 Summer World University Games (2023年夏季世界大学生运动会) type: Aug 8, 2023 – Aug 19, 2023.', '2023 Summer World University Games (2023年夏季世界大学生运动会) main_tab_text: Overview.', '2023 Summer World University Games (2023年夏季世界大学生运动会) kgmid: /g/11hzkdc1v8.', '2023 Summer World University Games (2023年夏季世界大学生运动会) dates: Aug 8, 2023 – Aug 19, 2023.', '2023 Summer World University Games (2023年夏季世界大学生运动会) location: Yekaterinburg.', '2023 Summer World University Games (2023年夏季世界大学生运动会) main_venue: Ekaterinburg Arena (opening/closing ceremonies).', '2023 Summer World University Games (2023年夏季世界大学生运动会) motto: For You.', '2023 Summer World University Games (2023年夏季世界大学生运动会) opening: 8 August (cancelled).', '2023 Summer World University Games (2023年夏季世界大学生运动会) sport: 18.', '2023年夏季世界大学生运动会（英语：XXXII 2023 Summer World University Games）简称为叶卡捷琳堡大运会，是第32届夏季世界大学生运动会。原定于2023年8月8日至19日在 ...', '成都第31届世界大学生夏季运动会（Chengdu 2021 FISU World University Games），简称“成都大运会”，将于2023年7月28日至8月8日在中国成都举办。', '2023年冬季世界大学生运动会（英语：2023 FISU Winter World University Games），正式名称为第31届冬季世界大学生运动会，也被称为2023年普莱西德湖大冬会或者2023年世界大冬会，于2023年1月12-22日在美国纽约州埃塞克斯县的普莱西德湖举行，是大学生参与的冬季体育项目世界 ...', '中新社成都6月25日电据国际大学生体育联合会消息，原定于今年6月在四川成都举行的第31届世界大学生夏季运动会(简称成都大运会)延期到2023年7月28日至8月8日举行。 同时，年龄限制和参赛资格将进行调整，以便符合2021和2022年(延期)参赛资格的学生参加。', '世界大学生夏季运动会，叶卡捷琳堡2023. 2019年7月2日，在国际大学生体育联合会（FISU）执行委员会会议上，决定委托叶卡捷琳堡主办2023年第三十二届世界大学生夏季运动会。 执行委员会的所有23名成员都支持叶卡捷琳堡的申请，叶卡捷琳堡是2023年世界大学生运动会的唯一申请者。 ...', '成都大运会是新冠疫情发生以来我国首个以开放形式举办的大型国际体育综合赛事，承载着党中央、国务院的关怀与重托，同时也备受国内国际社会高度关注，是一次重要的国际性体育赛事和文化盛会，也是促进世界青年大学生交流融合的重要平台。 我想用三句话介绍本届大运会的重要意义。 首先，这是一次来之不易的 ...', '... 2023年7月28日至8月8日在四川成都举行。大运会是面向全球大学生、规模仅次于奥林匹克运动会的世界综合性运动会，是全世界大学生运动员同台竞技的赛场 ...', '2023年7月28日，成都第31届世界大学生夏季运动会（以下简称：成都大运会）就将在东安湖体育公园盛大开幕，届时成都将向世界奉献一场独具魅力、别样精彩的青春盛会。', '成都大运会作为我国后疫情时代的首场国际体育赛事和2023年重大国家主场外交活动，是促进世界青年大学生交流发展的重要平台，是展现中国形象、讲好中国故事 ...', '世界大学生运动会自诞生以来，就一直是青春的盛会、团结的盛会、友谊的盛会。 ——我们要携手世界青年，以青春的活力促进世界和平与发展。国之交在于民相亲 ...']\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mFollow up: 2023年大运会举办地在哪里？\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3m第31届世界大学生夏季运动会，也就是成都大运会将于7月28日至8月8日举行。 今天（7月13日），成都大运会主媒体中心在东安湖体育公园开始试运行。\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "So the final answer is: 成都\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'成都'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 实际运行 Agent，查询问题（有歧义）\n",
    "self_ask_with_search.run(\n",
    "    \"2023年大运会举办地在哪里？\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "e1cf918e-a58a-4790-a4c4-2109f23dd064",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "成都举办的是第十一届大运会。\n"
     ]
    }
   ],
   "source": [
    "# Reason-only 答案（错误）\n",
    "print(llm(\"成都举办的大运会是第几届大运会？\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "32021fdf-2597-4dde-a425-13650904671f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "2023年大运会将在日本东京举办。\n"
     ]
    }
   ],
   "source": [
    "# Reason-only 答案（错误）\n",
    "print(llm(\"2023年大运会举办地在哪里？\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b73c7bd9-a835-41c1-bf28-4e203c22538b",
   "metadata": {},
   "source": [
    "#### 使用 GPT-4 作为大语言模型实现更优的 ReAct 范式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "d98ba940-a6e8-477e-83a9-2e20115ff51d",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chat_models import ChatOpenAI\n",
    "\n",
    "chat_model = ChatOpenAI(model=\"gpt-4-1106-preview\", temperature=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "fc4347f2-4a16-4406-92c7-d2156478bb56",
   "metadata": {},
   "outputs": [],
   "source": [
    "self_ask_with_search_chat = initialize_agent(\n",
    "    tools, chat_model, agent=AgentType.SELF_ASK_WITH_SEARCH, verbose=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "25978771-8e69-41f2-b9e8-b287d846e1cd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mYes.\n",
      "Follow up: What is the English translation of \"2023年大运会\"?\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3mNo good search result found\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mThe phrase \"2023年大运会\" translates to \"2023 Universiade\" in English. The Universiade is an international multi-sport event, organized for university athletes by the International University Sports Federation (FISU).\n",
      "\n",
      "Follow up: Where is the 2023 Universiade being held?\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3mLake Placid 2023 FISU World University Games Winter, 12-22 January. Welcome back to legendary Lake Placid, where many Universiade and Olympic Legends were born.\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mSo the final answer is: Lake Placid, New York, United States\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'Lake Placid, New York, United States'"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# GPT-4 based ReAct 答案（正确）\n",
    "self_ask_with_search_chat.run(\n",
    "    \"2023年大运会举办地在哪里？\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "94da622a-8bdd-4cf3-bc7a-bcfbf88c54f4",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
